#!/usr/bin/perl
# Version 0.2.1

$testcase = "dd_retransmit";

# 1 = PASS
# 2 = FAIL
# 3 = INCONCLUSIVE
$verdict = 3;

$dumpfile = "$testcase.dump";
$logfile = "$testcase.log";

if ($#ARGV ne 4) {
        print("Usage: $testcase.pl dump_file1 dump_file2 dump_file3 dump_file4 log_file");
        exit 1;
}

$dumpfile[0] = $ARGV[0];
$dumpfile[1] = $ARGV[1];
$dumpfile[2] = $ARGV[2];
$dumpfile[3] = $ARGV[3];
$logfile = $ARGV[4];

#------------------------------------------------------------------------------
@local_verdict = (3, 3, 3, 3);

$success = 1;
open(DUMPFILE, $dumpfile[0]) or $success = 0;

$state = 0;

if($success eq 1) {
	while(<DUMPFILE>) {
		if($state eq 0) {
		# there must be exactly one dd packet with the I bit clear from 0.0.1.25
			if(/0\.0\.1\.25 > (.*) OSPFv2-dd/) {
				if($_ !~ /backbone E I/) {
					# found the non-initial dd packet
					$state = 1;
				}
			}
		} elsif($state eq 1) {
			# after that there must not be any dd-packets from 0.0.1.17 in the log
			if(/0\.0\.1\.25 > (.*) OSPFv2-dd/) {
				# bad thing!
				$state = 2;
			}
		}
	}
	close(DUMPFILE);
	
	if($state eq 1) {
		$local_verdict[0] = 1;
	} elsif($state eq 0) {
		$local_verdict[0] = 3;
	}else {
		$local_verdict[0] = 2;
	}
}



$state = 0;
$success = 1;
open(DUMPFILE, $dumpfile[1]) or $success = 0;

if($success eq 1) {
	$num_dd = 0;
	
	while(<DUMPFILE>) {
		
		if( $state eq 0 ) {
			# until time 180 the tr only builds up its lsdb - ignore this process
			
			@l = split(/ /, $_);
			# now look at the time
			@ti = split(/\./, $l[0]);
			@ts = split(/:/, $ti[0]);
			
			$secs = $ts[2] + ($ts[1] + $ts[0] * 60) * 60; # secs contains the sim time in seconds
		
			if ($secs > 180) {
				# now there should come the interesting packets
				$state = 1;
			}
		}
		if( $state eq 1 ) {
			# wait for the third dd-packet (2nd non initial) and store its seq. no.
			if(/0\.0\.1\.17 > (.*) OSPFv2-dd (.*) M S (.*) /) {
				$num_dd++;
				
				if($num_dd eq 2) {
					$dd_cont = $_;
					$dd_cont =~ s/^(.*?) (.*)$/$2/;
				}
				if($num_dd eq 3) {
					# the next dd packet from the rut must be a retransmission, i.e. the contents 
					# must be the same 
					$dd_tmp = $_;
					$dd_tmp =~ s/^(.*?) (.*)$/$2/;
					if($dd_tmp ne $dd_cont) {
						$state = 2;
					} else {
						$state = 3;
					}
				}	
			}
		}
	}
	close(DUMPFILE);
	
	if($state eq 3) {
		$local_verdict[1] = 1;
	} elsif($state eq 0) {
		$local_verdict[1] = 3;
	}else {
		$local_verdict[1] = 2;
	}
}

$success = 1;
$state = 0;
open(DUMPFILE, $dumpfile[2]) or $success = 0;

if($success eq 1) {
	$dd_cont = "initial";
	$dd_ti = "00:00:00.0";
	while(<DUMPFILE>) {
		# find the first non-initial dd packet from tr
		if($state eq 0) {
			if(/0\.0\.1\.9 > (.*) OSPFv2-dd/) {
				if($_ !~ /backbone E I/) {
					# found the non-initial dd packet
					$state = 1;
				}
			}
		}
		# now look at the dd packets from the RUT
		if($state eq 1) {
			if(/(.*?) 0\.0\.1\.10 > (.*) OSPFv2-dd/) {
				@ti = split(/:/, $1);
				$ts = $ti[2] + ($ti[1] + $ti[0] * 60) * 60;
				
				$dd_tmp = $_;
				$dd_tmp =~ s/^(.*?) (.*)$/$2/;
				if($dd_cont ne "initial") {
					# compare if the packet is a retransmission
					if( $dd_cont ne $dd_tmp ) {
						$state = $state | 2;
					}
					# compare if the dd packets follow  RxmtInterval after each other
					if( (($ts - $dd_ti) > 5.2) || (($ts - $dd_ti) < 4.8) ) {
						$state = $state | 4;
					}
				}
				
				$dd_cont = $dd_tmp;
				$dd_ti = $ts;
			}
		}
	}
	close(DUMPFILE);
	
	if($state eq 1) {
		$local_verdict[2] = 1;
	} elsif($state eq 0) {
		$local_verdict[2] = 3;
	}else {
		$local_verdict[2] = 2;
	}
}

$success = 1;
$state = 0;
open(DUMPFILE, $dumpfile[3]) or $success = 0;

if($success eq 1) {
	
	$dd_cont = "initial";
	$dd_over = 0;
	while(<DUMPFILE>) {
		if( $state eq 0 ) {
			# until time 180 the tr only builds up its lsdb - ignore this process
			
			@l = split(/ /, $_);
			# now look at the time
			@ti = split(/\./, $l[0]);
			@ts = split(/:/, $ti[0]);
			
			$secs = $ts[2] + ($ts[1] + $ts[0] * 60) * 60; # secs contains the sim time in seconds
		
			if ($secs > 180) {
				# now there should come the interesting packets
				$state = 1;
			}
		} else {
			# now look for the dd process to be over and find the TR's retransmission
			if(/0\.0\.1\.(1|2) > (.*) OSPFv2-dd/) {
			
				if($1 eq "1") {
					if($state eq 2) {
						$dd_tmp = $dd_cont;
					}
					
					$dd_cont = $_;
					$dd_cont =~ s/^(.*?) (.*)$/$2/;
					
					if($state eq 2) {
						if($dd_cont eq $dd_tmp) {
							# Passed the test!
							$state = 3;
						}
					}
				}
				
				if($state eq 1) {
					if($_ !~ /backbone E (I\/)?M/) {
						$dd_over = $dd_over | 1;
					}
				} else {
					if($_ !~ /backbone E (I\/)?M\//) {
						$dd_over = $dd_over | 2;
					}
				}
				
				if($dd_over eq 3) {
					$state = 2;
				}
			}
		}
	}
	close(DUMPFILE);
	
	if($state eq 1) {
		$local_verdict[3] = 1;
	} elsif($state eq 0) {
		$local_verdict[3] = 3;
	}else {
		$local_verdict[3] = 2;
	}
}


# print results
if ($local_verdict[0] eq 1) {
	print("Slave didn't retransmit dd packet. Test PASSED.\n");
} elsif ($local_verdict[0] eq 2) {
	print("Slave retransmitted dd packet. Test FAILED.\n");
} else {
	print("Cannot evaluate results. Test INCONCLUSIVE.\n");
}
if ($local_verdict[1] eq 1) {
	print("Slave properly retransmits dd packet. Test PASSED.\n");
} elsif ($local_verdict[1] eq 2) {
	print("Slave didn't retransmit its dd packet. Test FAILED.\n");
} else {
	print("Cannot evaluate results. Test INCONCLUSIVE.\n");
}
if ($local_verdict[2] eq 1) {
	print("Master retransmits DD packets every RxmtInterval. Test PASSED.\n");
} elsif ($local_verdict[2] eq 2) {
	print("Master does not retransmit DD packets every RxmtInterval. Test FAILED.\n");
} else {
	print("Cannot evaluate results. Test INCONCLUSIVE.\n");
}
if ($local_verdict[3] eq 1) {
	print("Slave retransmits last DD pcket in state > EXCHANGE. Test PASSED.\n");
} elsif ($local_verdict[3] eq 2) {
	print("Slave does not retransmit last DD pcket in state > EXCHANGE. Test FAILED.\n");
} else {
	print("Cannot evaluate results. Test INCONCLUSIVE.\n");
}


$verdict = $local_verdict[0];
if ($local_verdict[1] ne $verdict) {
	if($local_verdict[1] eq 2) {
		$verdict = 2;
	} elsif ($local_verdict[1] eq 3) {
		if($verdict ne 2) {
			$verdict = 3;
		}
	}	
}
if ($local_verdict[2] ne $verdict) {
	if($local_verdict[2] eq 2) {
		$verdict = 2;
	} elsif ($local_verdict[2] eq 3) {
		if($verdict ne 2) {
			$verdict = 3;
		}
	}	
}
if ($local_verdict[3] ne $verdict) {
	if($local_verdict[3] eq 2) {
		$verdict = 2;
	} elsif ($local_verdict[3] eq 3) {
		if($verdict ne 2) {
			$verdict = 3;
		}
	}	
}
#------------------------------------------------------------------------------
print("### VERDICT for $testcase: ");

if ($verdict eq 1) { 
        print("PASS"); 
} elsif ($verdict eq 2) {
        print("FAIL");
} else {
        print("INCONCLUSIVE");
}

print(" ###\n");